﻿using Serilog;
using Serilog.Debugging;
using Serilog.Events;
using Serilog.Formatting.Json;
using Serilog.Sinks.Elasticsearch;
using Serilog.Sinks.File;
using Serilog.Sinks.SystemConsole.Themes;
using Sustainalytics.Admin.Synchronization.Utility;
using Sustainalytics.Utils;
using System;
using System.Threading;

namespace Sustainalytics.Companies
{
    public class CompaniesSerilog
    {

        public static Lazy<CompaniesSerilog> _lazyLog = new Lazy<CompaniesSerilog>(InitLog, LazyThreadSafetyMode.ExecutionAndPublication);
        private readonly ILogger _logger;


        public static CompaniesSerilog Log
        {
            get
            {
                return _lazyLog.Value;
            }
        }

        public static CompaniesSerilog InitLog()
        {
            var log = new CompaniesSerilog();
            return log;

        }

        public CompaniesSerilog()
        {
            var loggerConfig = new LoggerConfiguration()
                  .MinimumLevel.Debug()
                  .WriteTo.Console(theme: SystemConsoleTheme.Literate)
                  .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200")) // for the docker-compose implementation
                  {
                      IndexFormat = "testcompanysearch-{0:yyyy.MM.dd}",
                      AutoRegisterTemplate = true,
                      //BufferBaseFilename = "./buffer",
                      RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway,
                      FailureCallback = e => Console.WriteLine("Unable to submit event " + e.MessageTemplate),
                      EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog |
                                         EmitEventFailureHandling.WriteToFailureSink |
                                         EmitEventFailureHandling.RaiseCallback,
                      FailureSink = new FileSink("../failuresCompanySearch-"+ DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss") + ".txt", new JsonFormatter(), null)
                  });
            _logger = loggerConfig.CreateLogger();

            SelfLog.Enable(Console.Error);
        }

        public void ApplicationStartError(Exception e)
        {
            if (e == null)
                return;
            if (_logger.IsEnabled(LogEventLevel.Error))
                ApplicationStartError(e.GetType().ToString(), e.Message, ExceptionUtility.GetInfo(e, true));
        }

        public void ApplicationStartError(string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            _logger.Error("ApplicationStartError: " + exceptionType, exceptionMessage, exceptionInformation);
        }
        public void ApplicationStopError(Exception e)
        {
            if (e == null)
                return;
            if (_logger.IsEnabled(LogEventLevel.Error))
                ApplicationStopError(e.GetType().ToString(), e.Message, ExceptionUtility.GetInfo(e, true));
        }

        public void ApplicationStopError(string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            _logger.Error("ApplicationStopError: " + exceptionType, exceptionMessage, exceptionInformation);

        }

        public void ApplicationUnhandledException(Exception e)
        {
            if (e == null)
                return;
            if (_logger.IsEnabled(LogEventLevel.Error))
                ApplicationUnhandledException(e.GetType().ToString(), e.Message, ExceptionUtility.GetInfo(e, true));
        }

        public void ApplicationUnhandledException(string exceptionType, string exceptionMessage, string exceptionInformation)
        {
            _logger.Error("ApplicationUnhandledException: " + exceptionType, exceptionMessage, exceptionInformation);

        }

        public void InitAccountsController()
        {
            var eventId = 3;
            if (_logger.IsEnabled(LogEventLevel.Verbose))
            {
                _logger.Verbose("EventId: {eventId} for InitAccountsController.", eventId);
            }
        }
        public void InitAccountsControllerSuccess()
        {
            var eventId = 4;
            if (_logger.IsEnabled(LogEventLevel.Verbose))
            {
                _logger.Verbose("EventId: {eventId} for InitAccountsControllerSuccess.", eventId);
            }
        }

        public void InitAccountsControllerError(Exception ex)
        {
            Guard.ArgumentNotNull(ex, "InitAccountsControllerError");

            InitAccountsControllerError(ex.Message);
        }

        public void InitAccountsControllerError(string errorMsg)
        {
            var eventId = 5;
            if (_logger.IsEnabled(LogEventLevel.Verbose))
            {
                _logger.Error("EventId:{eventiId} for InitAccountsControllerError. Message: {Message}.", eventId, errorMsg);
            }
        }

        public void CompanySearch(string term, int skip, int take)
        {
            var eventId = 100;
            if (_logger.IsEnabled(LogEventLevel.Verbose))
            {
                _logger.Verbose("EventId {eventId} for the CompanySearch, {term}, {skip}, {take}", eventId, term, skip, take); ;
            }
        }

        public void CompanySearchSuccess(string term, int skip, int take)
        {
            var eventId = 101;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventId} for the CompanySearchSuccess , {term}, {skip}, {take}", eventId, term, skip, take);
            }
        }

        public void CompanySearchError(string term, int skip, int take, Exception ex)
        {
            Guard.ArgumentNotNull(ex, "CompanySearchException");

            this.CompanySearchError(term, skip, take, ex.Message);

        }

        public void CompanySearchError(string term, int skip, int take, string exceptionMessage)
        {
            var eventId = 102;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventiD} for the CompanySearchError {term}, {skip}, {take}, {exceptionMessage}", eventId, term, skip, take, exceptionMessage);
            }
        }

        public void GetCompanyById(string id)
        {
            var eventId = 200;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventId} for the GetCompanyById {id}", eventId, id);
            }
        }
        public void GetCompanyByIdSuccess(string id)
        {
            var eventId = 201;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventId} for the GetCompanyByIdSuccess {id}", eventId, id);
            }
        }

        public void GetCompanyByIdError(string id, Exception ex)
        {
            GetCompanyByIdError(id, ex.ToString());
        }


        public void GetCompanyByIdError(string id, string error)
        {
            var eventId = 201;
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                _logger.Error("EventId {eventId} for the GetCompanyByIdError {id}.Error Message {error}", eventId, id, error);
            }
        }
        public void GetCompanyByName(string name)
        {
            var eventId = 300;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventId}, for the GetCompanyByName {name}", eventId, name);
            }
        }

        public void GetCompanyByNameSuccess(string name)
        {
            var eventId = 301;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventId}, for the GetCompanyByNameSuccess name {name}", eventId, name);
            }
        }

        public void GetCompanyByNameError(string name, Exception ex)
        {
            {
                GetCompanyByNameError(name, ex.ToString());
            }
        }

        public void GetCompanyByNameError(string name, string error)
        {
            var eventId = 302;
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                _logger.Information("EventId {eventId}, for the GetCompanyByNameError name {name}. Error: {error}", eventId, name, error);
            }
        }

        public void GetCompanyByNameUrlFriendly(string nameUrlFriendly)
        {
            var eventId = 303;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventId}, for the GetCompanyByNameUrlFriendly {nameUrlFriendly}.", eventId, nameUrlFriendly);
            }
        }

        public void GetCompanyByNameUrlFriendlySuccess(string nameUrlFriendly)
        {
            var eventId = 304;
            _logger.Information("EventId {eventId}, for the GetCompanyByNameUrlFriendlySucces {nameUrlFriendly}.", eventId, nameUrlFriendly);
        }

        public void GetCompanyByNameUrlFriendlyError(string nameUrlFriendly, Exception ex)
        {
            GetCompanyByNameUrlFriendlyError(nameUrlFriendly, ex.ToString());
        }

        public void GetCompanyByNameUrlFriendlyError(string nameUrlFriendly, string error)
        {
            var eventId = 305;
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                _logger.Error("Event {eventId} GetCompanyByNameUrlFriendlyError {nameUrlFriendly}. Error: {error}", eventId, nameUrlFriendly, error);
            }
        }

        public void CompanySearchCount(string term)
        {
            var eventId = 306;
            if (_logger.IsEnabled(LogEventLevel.Verbose))
            {
                _logger.Verbose("EventId {eventId} generated by CompanySearcCount {term}", eventId, term);
            }
        }

        public void CompanySearchCountSuccess(string term)
        {
            var eventId = 307;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventId} generated by CompanySeacrhCountSucces {term}", eventId, term);
            }

        }

        public void CompanySearchCountError(string term, Exception ex)
        {
            Guard.ArgumentNotNull(ex, "CompanySearchCountException");
            CompanySearchCountError(term, ex.Message);
        }

        public void CompanySearchCountError(string term, string exceptionMessage)
        {
            var eventId = 308;
            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                _logger.Error("EventId {eventId}. CompanySearchCountError {term}. Exception {exceptionMessage}", eventId, term, exceptionMessage);
            }
        }

        public void CompanyGrid(string term, int skip, int take)
        {
            var eventId = 309;
            if (_logger.IsEnabled(LogEventLevel.Verbose))
            {
                _logger.Verbose("EventId {evenId}. CompanyGrid {term}, {skip}, {take}.", eventId, skip, take);
            }
        }

        public void CompanyGridSuccess(string term, int skip, int take)
        {
            var eventId = 310;
            if (_logger.IsEnabled(LogEventLevel.Information))
            {
                _logger.Information("EventId {eventId}. CompanyGridSuccess {term}, {skip}, {take}.", eventId, term, skip, take);
            }
        }


        public void CompanyGridError(string term, int skip, int take, Exception ex)
        {
            Guard.ArgumentNotNull(ex, "CompanySearchException");
            this.CompanyGridError(term, skip, take, ex.Message);

        }
        public void CompanyGridError(string term, int skip, int take, string exceptionMessage)
        {
            var eventId = 311;

            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                _logger.Error("EventId {eventId}. CompanyGridError {term}, {skip}, {take}. ExceptionMessage {exceptionMessage}", eventId, term, skip, take, exceptionMessage);
            }
        }

        public void OpenConnectionSucces()
        {
            var eventId = 312;

            if (_logger.IsEnabled(LogEventLevel.Debug))
            {
                _logger.Debug("EventId {eventId}. Open connection was successful.", eventId);
            }
        }

        public void OpenConnectionError(Exception ex)
        {
            var eventId = 313;

            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                _logger.Error("EventId {eventId}. An error has ocured while opening the connection.", eventId, ex.Message);
            }
        }

        public void ReadCompaniesSucces()
        {
            var eventId = 314;

            if (_logger.IsEnabled(LogEventLevel.Debug))
            {
                _logger.Debug("EventId {eventId}. Reading companies was successful.", eventId);
            }
        }

        public void ReadCompaniesError(Exception ex)
        {
            var eventId = 315;

            if (_logger.IsEnabled(LogEventLevel.Error))
            {
                _logger.Error("EventId {eventId}. An error has ocured while opening the connection", eventId, ex.Message);
            }
        }
    }
}
